package com.nbplus.vnpy.netty;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import cn.hutool.json.JSONObject;
import cn.hutool.json.XML;
import com.fasterxml.jackson.databind.JsonNode;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import com.fasterxml.jackson.databind.ObjectMapper;

public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter{

    /**
     * 从服务端收到新的数据时，这个方法会在收到消息时被调用
     *
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg){
        String msgStr  = msg.toString();
        try {
            if(msgStr.contains("FaceReaderAPI.Data.Classification")){
                String xmlStr = msg.toString().split("FaceReaderAPI.Data.Classification")[1];
                String replace = xmlStr.replace("<?xml version=\"1.0\"?>\n" +
                        "<Classification xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", "");
                /*System.out.println(replace);*/
                JSONObject json = XML.toJSONObject(replace);
                System.out.println(json.toStringPretty());
            }
        } catch (Exception e) {
            //System.out.println(e);
        }

        System.out.println("--------------------------------");
       /* System.out.println("channelRead:read msg:"+msg.toString());
        byte[] bytes = hexStringToByteArray(msg);
        System.out.println("收到服务端十六进制消息: " + bytesToHexString(bytes));*/
        //回应服务端
        //ctx.write("I got server message thanks server!");
    }

    /**
     * 从服务端收到新的数据、读取完成时调用
     *
     * @param ctx
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws IOException
    {
        System.out.println("channelReadComplete");
        ctx.flush();
    }

    /**
     * 当出现 Throwable 对象才会被调用，即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws IOException
    {
        System.out.println("exceptionCaught");
        cause.printStackTrace();
        ctx.close();//抛出异常，断开与客户端的连接
    }
    private static String startLog = "38 01 00 00 24 00 00 00 46 61 63 65 52 65 61 64 65 72 41 50 49 2E 4D 65 73 73 61 67 65 73 2E 41 63 74 69 6F 6E 4D 65 73 73 61 67 65 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 3F 3E 0D 0A 3C 41 63 74 69 6F 6E 4D 65 73 73 61 67 65 20 78 6D 6C 6E 73 3A 78 73 64 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 31 2F 58 4D 4C 53 63 68 65 6D 61 22 20 78 6D 6C 6E 73 3A 78 73 69 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 31 2F 58 4D 4C 53 63 68 65 6D 61 2D 69 6E 73 74 61 6E 63 65 22 3E 0D 0A 20 20 3C 49 64 3E 36 64 35 63 35 36 38 37 2D 62 33 33 65 2D 34 34 66 34 2D 61 32 33 39 2D 30 62 63 30 32 36 33 34 61 39 31 32 3C 2F 49 64 3E 0D 0A 20 20 3C 41 63 74 69 6F 6E 54 79 70 65 3E 46 61 63 65 52 65 61 64 65 72 5F 53 74 61 72 74 5F 44 65 74 61 69 6C 65 64 4C 6F 67 53 65 6E 64 69 6E 67 3C 2F 41 63 74 69 6F 6E 54 79 70 65 3E 0D 0A 3C 2F 41 63 74 69 6F 6E 4D 65 73 73 61 67 65 3E";


    /**
     * 客户端与服务端第一次建立连接时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception, IOException
    {
        super.channelActive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        System.out.println("channelActive:"+clientIp+ctx.name());
        ByteBuf message = null;
        ByteBuf buf1 = Unpooled.wrappedBuffer(hexStringToByteArray(startLog.replaceAll(" ","")));
        ctx.writeAndFlush(buf1);
    }

    /**
     * 客户端与服务端 断连时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception, IOException
    {
        super.channelInactive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        ctx.close(); //断开连接时，必须关闭，否则造成资源浪费
        System.out.println("channelInactive:"+clientIp);
    }


    private static String hexStringToString1(String hexString) {
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("输入的十六进制字符串长度不正确");
        }

        try {
            int byteArrayLength = hexString.length() / 2;
            byte[] byteArray = new byte[byteArrayLength];

            for (int i = 0; i < byteArrayLength; i++) {
                int index = i * 2;
                String hex = hexString.substring(index, index + 2);
                byte ascii = (byte) Integer.parseInt(hex, 16);
                byteArray[i] = ascii;
            }

            return new String(byteArray, "UTF-8");
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("输入的十六进制字符串包含非法字符");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("不支持的字符编码");
        }
    }

    // 将十六进制字符串转换为字节数组
    private static byte[] hexStringToByteArray(String hexString) {
        int len = hexString.length();
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            String subStr = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(subStr, 16);
        }
        return bytes;
    }

    // 将字节数组转换为十六进制字符串
    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}
